bitkeeper revision 1.255 (3ee5f6d5vkkWKWqCJgu8yj_PRuBcLQ)
authorrgr22@boulderdash.cl.cam.ac.uk <rgr22@boulderdash.cl.cam.ac.uk>
Tue, 10 Jun 2003 15:18:45 +0000 (15:18 +0000)
committerrgr22@boulderdash.cl.cam.ac.uk <rgr22@boulderdash.cl.cam.ac.uk>
Tue, 10 Jun 2003 15:18:45 +0000 (15:18 +0000)
adding resource usage accounting for network usage

xen/common/network.c
xen/include/hypervisor-ifs/network.h
xen/include/xeno/vif.h
xen/net/dev.c
xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/dom0/dom0_core.c

index 242f6ccadf8562416e900932f817ac0772d2434e..30cdf81441b644451a666331815fe5b91f4ec0bf 100644 (file)
@@ -211,29 +211,67 @@ void unlink_net_vif(net_vif_t *vif)
 /* vif_query - Call from the proc file system to get a list of indexes
  * in use by a particular domain.
  */
-void vif_query(vif_query_t *vq)
+int vif_query(vif_query_t *vq)
 {
     net_vif_t *vif;
     struct task_struct *p;
-    char buf[128];
+    int buf[32];
     int i;
+    int count = 0;
 
-    if ( !(p = find_domain_by_id(vq->domain)) ) 
-        return;
-
-    *buf = '\0';
+    if ( !(p = find_domain_by_id(vq->domain)) ) {
+        buf[0] = -1;
+        copy_to_user(vq->buf, buf, sizeof(int));
+        return -ENOSYS;
+    }
 
     for ( i = 0; i < MAX_DOMAIN_VIFS; i++ )
     {
         vif = p->net_vif_list[i];
         if ( vif == NULL ) continue;
-        sprintf(buf + strlen(buf), "%d\n", i);
+        buf[++count] = i;
     }
 
-    copy_to_user(vq->buf, buf, strlen(buf) + 1);
+    buf[0] = count;
+
+    copy_to_user(vq->buf, buf, (buf[0] + 1) * sizeof(int));
     
     put_task_struct(p);
+
+    return 0;
 }
+
+/* vif_getinfo - Call from the proc file system to get info about a specific
+ * vif in use by a particular domain.
+ */
+int vif_getinfo(vif_getinfo_t *info)
+{
+    struct task_struct *p;
+    net_vif_t *vif;
+
+    info->total_bytes_sent =
+    info->total_bytes_received =
+    info->total_packets_sent =
+    info->total_packets_received = -1;
+
+    if ( !(p = find_domain_by_id(info->domain)) )
+        return -ENOSYS;
+
+    vif = p->net_vif_list[info->vif];
+
+    if(vif == NULL)
+        return -ENOSYS;
+
+    info->total_bytes_sent              = vif->total_bytes_sent;
+    info->total_bytes_received          = vif->total_bytes_received;
+    info->total_packets_sent            = vif->total_packets_sent;
+    info->total_packets_received        = vif->total_packets_received;
+
+    put_task_struct(p);
+
+    return 0;
+}
+
         
 /* ----[ Net Rule Functions ]-----------------------------------------------*/
 
@@ -517,9 +555,16 @@ long do_network_op(network_op_t *u_network_op)
     }
     break;
 
+    case NETWORK_OP_VIFGETINFO:
+    {
+        ret = vif_getinfo(&op.u.vif_getinfo);
+        copy_to_user(u_network_op, &op, sizeof(op));
+    }
+    break;
+
     case NETWORK_OP_VIFQUERY:
     {
-        vif_query(&op.u.vif_query);
+        ret = vif_query(&op.u.vif_query);
     }
     
     default:
index fa8a365f217f682ecbd4772169659cf67aa771d5..09703df92504fcd188cb47aedd5eb9ddaf9a941d 100644 (file)
@@ -123,9 +123,20 @@ typedef struct net_rule_st
 typedef struct vif_query_st
 {
     unsigned int    domain;
-    char            *buf;   /* reply buffer -- guest virtual address */
+    int             *buf;   /* reply buffer -- guest virtual address */
 } vif_query_t;
 
+typedef struct vif_getinfo_st
+{
+    unsigned int        domain;
+    unsigned int        vif;
+    /* domain & vif are supplied by dom0, the rest are response fields */
+    long long           total_bytes_sent;
+    long long           total_bytes_received;
+    long long           total_packets_sent;
+    long long           total_packets_received;
+} vif_getinfo_t;
+
 /* Network trap operations and associated structure. 
  * This presently just handles rule insertion and deletion, but will
  * evenually have code to add and remove interfaces.
@@ -135,6 +146,7 @@ typedef struct vif_query_st
 #define NETWORK_OP_DELETERULE   1
 #define NETWORK_OP_GETRULELIST  2
 #define NETWORK_OP_VIFQUERY     3
+#define NETWORK_OP_VIFGETINFO   4
 
 typedef struct network_op_st 
 {
@@ -143,6 +155,7 @@ typedef struct network_op_st
     {
         net_rule_t net_rule;
         vif_query_t vif_query;
+        vif_getinfo_t vif_getinfo;
     }
     u;
 } network_op_t;
index 8e4fcab444bbe4ff0cf1221798a48a66a3d1d331..3c38668bd65a33ac5d4d99f62f1ca2c4738430ba 100644 (file)
@@ -66,6 +66,12 @@ typedef struct net_vif_st {
     unsigned int tx_req_cons;
     unsigned int tx_resp_prod; /* private version of shared variable */
 
+    /* Usage accounting */
+    long long total_bytes_sent;
+    long long total_bytes_received;
+    long long total_packets_sent;
+    long long total_packets_received;
+
     /* Miscellaneous private stuff. */
     struct task_struct *domain;
     unsigned int idx; /* index within domain */
index ce2795f3a0986a8b7a0ee507aa5ebdf9eae44c0d..7619fa5361896838a583b9008eadb8a51f9f792a 100644 (file)
@@ -1882,6 +1882,10 @@ long do_net_update(void)
                 make_tx_response(vif, tx.id, RING_STATUS_OK);
             }
 
+            /* record the transmission so they can be billed */
+            vif->total_packets_sent++;
+            vif->total_bytes_sent += tx.size;
+
         tx_unmap_and_continue:
             unmap_domain_mem(g_data);
             spin_unlock_irq(&current->page_lock);
@@ -2037,6 +2041,10 @@ static void make_rx_response(net_vif_t     *vif,
         guest_event_notify(cpu_mask);    
     }
     spin_unlock_irqrestore(&vif->rx_lock, flags);
+
+    /* record this so they can be billed */
+    vif->total_packets_received++;
+    vif->total_bytes_received += size;
 }
 
 
index 3dadd5cebd144e542efa7378b24b677acde252b3..b42abc45e4fac77b927eb5ae850c1c8f88001c6b 100644 (file)
@@ -82,7 +82,8 @@ static int cmd_read_proc(char *page, char **start, off_t off,
 
 static ssize_t dom_vif_read(struct file * file, char * buff, size_t size, loff_t * off)
 {
-    char hyp_buf[128];
+    int hyp_buf[32];
+    char buf[128];
     network_op_t op;
     static int finished = 0;
 
@@ -93,20 +94,30 @@ static ssize_t dom_vif_read(struct file * file, char * buff, size_t size, loff_t
     }
     
     op.cmd = NETWORK_OP_VIFQUERY;
-    op.u.vif_query.domain = (unsigned int) ((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
+    op.u.vif_query.domain = (unsigned int)
+        ((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
     op.u.vif_query.buf = hyp_buf;
 
-    strcpy(hyp_buf, "Error getting domain's vif list from hypervisor.\n"); // This will be replaced if everything works.
+    (void) HYPERVISOR_network_op(&op);
+
+    if(hyp_buf[0] < 0) {
+        strcpy(buf, "Error getting domain's vif list from hypervisor.\n");
+    } else {
+        int i;
+        int len = 0;
+        strcpy(buf, "No vif found");
 
-    (void)HYPERVISOR_network_op(&op);
+        for(i = 1; i <= hyp_buf[0] && len < 127; i++)
+            len += snprintf(buf + len, 127 - len, "%d\n", hyp_buf[i]);
+    }
 
-    if (*off >= (strlen(hyp_buf)+1)) return 0;
+    if (*off >= (strlen(buf)+1)) return 0;
     
-    copy_to_user(buff, hyp_buf, strlen(hyp_buf));
+    copy_to_user(buff, buf, strlen(buf));
     
     finished = 1;
     
-    return strlen(hyp_buf)+1;
+    return strlen(buf)+1;
 }
 
 struct file_operations dom_vif_ops = {
@@ -115,8 +126,12 @@ struct file_operations dom_vif_ops = {
 
 static ssize_t dom_usage_read(struct file * file, char * buff, size_t size, loff_t * off)
 {
-    char hyp_buf[128];
+    char str[256];
+    int vifs[32];
     dom0_op_t op;
+    network_op_t netop;
+    int i, end;
+    unsigned int domain;
     static int finished = 0;
 
     if ( finished )
@@ -125,21 +140,46 @@ static ssize_t dom_usage_read(struct file * file, char * buff, size_t size, loff
         return 0;
     }
 
-    op.cmd = DOM0_GETDOMAININFO;
-    op.u.getdominfo.domain = (unsigned int)
+    domain = (unsigned int)
         ((struct proc_dir_entry *)file->f_dentry->d_inode->u.generic_ip)->data;
+    op.cmd = DOM0_GETDOMAININFO;
 
-    (void)HYPERVISOR_dom0_op(&op);
+    op.u.getdominfo.domain = domain;
 
-    snprintf(hyp_buf, 128, "cpu: %lld\n", op.u.getdominfo.cpu_time);
+    (void) HYPERVISOR_dom0_op(&op);
+
+    end = snprintf(str, 256, "cpu: %lld\n", op.u.getdominfo.cpu_time);
+
+    netop.cmd = NETWORK_OP_VIFQUERY;
+    netop.u.vif_query.domain = domain;
+    netop.u.vif_query.buf = vifs;
+
+    (void) HYPERVISOR_network_op(&netop);
+
+    for(i = 1; i <= vifs[0]; i++) {
+        netop.cmd = NETWORK_OP_VIFGETINFO;
+        netop.u.vif_getinfo.domain = domain;
+        netop.u.vif_getinfo.vif = vifs[i];
+
+        (void) HYPERVISOR_network_op(&netop);
+
+        end += snprintf(str + end, 255 - end,
+                "vif%d: sent %lld bytes (%lld packets) "
+                "received %lld bytes (%lld packets)\n",
+                vifs[i],
+                netop.u.vif_getinfo.total_bytes_sent,
+                netop.u.vif_getinfo.total_packets_sent,
+                netop.u.vif_getinfo.total_bytes_received,
+                netop.u.vif_getinfo.total_packets_received);
+    }
 
-    if (*off >= (strlen(hyp_buf) + 1)) return 0;
+    if (*off >= end + 1) return 0;
     
-    copy_to_user(buff, hyp_buf, strlen(hyp_buf));
+    copy_to_user(buff, str, end);
 
     finished = 1;
 
-    return strlen(hyp_buf) + 1;
+    return end + 1;
 }
 
 struct file_operations dom_usage_ops = {